package dataflowscheme.engine.core;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

import org.apache.log4j.Logger;

import dataflowScheme.SynchroPort;

/**
 * Encapsulate data-flow entity Stopper. When it will receive all 
 * required signals, then will end the program.
 * 
 * @author <a href="mailto:misiak7@gmail.com">Michal Antolik</a>
 *
 */
public class CStopper implements IConnectableEntity {

	/** synchronization aim of Main thread. In program runtime 
	 * phase Main thread is waiting while doneSignal is decreased to zero */
	private final CountDownLatch doneSignal;
	
	/** EMF ecore instance */
	private final dataflowScheme.Stopper eStopper;
	
	private Set<String> ports = new HashSet<String>();
	
	/** set of ports, which already have received a signal */
	private Set<String> fullPorts = new HashSet<String>();

	static Logger log = Logger.getLogger(CStopper.class);
	
	public CStopper(dataflowScheme.Stopper eStopper, CountDownLatch doneSignal) {
		this.doneSignal = doneSignal;
		this.eStopper = eStopper;
	}
	
	public void init(){
		for(SynchroPort p : eStopper.getPorts()){
			ports.add(p.getName());
		}
	}
	
	/* (non-Javadoc)
	 * @see dataflowscheme.engine.core.IConnectableEntity#addConnection(String portName, IConnectableEntity oppossiteEntity, String oppossitePortName)
	 */
	public void addConnection(String portName,
			IConnectableEntity oppossiteEntity, String oppossitePortName) {
		//not necessary, CStopper just receive signals, is not communicating with other entities
	}

	private void run(){
		doneSignal.countDown();
	}
	
	/* (non-Javadoc)
	 * @see dataflowscheme.engine.core.IConnectableEntity#receiveData(Object data, String portName)
	 */
	public boolean receiveData(Object data, String portName) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see dataflowscheme.engine.core.IConnectableEntity#receiveResponse(EventMsg event, String portName)
	 */
	public void receiveResponse(EventMsg event, String portName) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see dataflowscheme.engine.core.IConnectableEntity#receiveSignal(String portName)
	 */
	public boolean receiveSignal(String portName) {
		if(!ports.contains(portName)){
			log.error("Trying to set data to unknown port '" + portName + "'.");
			return false;
		}
		
		if(fullPorts.contains(portName)){
			//we have a token, therefore reject attempt of sender
			return false;
		} else {
			fullPorts.add(portName);
		}

		if(fullPorts.size() == ports.size()){
			//going down, bye bye
			run();
		}
		
		return true;
	}

	/* (non-Javadoc)
	 * @see dataflowscheme.engine.core.IConnectableEntity#getName()
	 */
	public String getName() {
		return "STOPPER";
	}

}
